﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Win32;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils
{
    public class RegReader
    {
        /// <summary>
        /// 判断是否64位系统。
        /// 来源：https://www.xp.cn/b.php/80188.html
        /// </summary>
        /// <param name="hProcess"></param>
        /// <param name="lpSystemInfo"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);
        private static bool Is64Bit()
        {
            bool retVal;
            IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);
            return retVal;
        }

        //static void Read64RegSample(string[] args)
        //{
        //    string myParentKeyName = "HKEY_LOCAL_MACHINE";
        //    string mySubKeyName = @"SOFTWARE\EricSun\MyTestKey";
        //    string myKeyName = "MyKeyName";

        //    string value = string.Empty;
        //    value = Get64BitRegistryKey(myParentKeyName, mySubKeyName, myKeyName);
        //    Console.WriteLine("The Value is: {0}", value);
        //}

        /// 32位程序访问64位注册表
        /// 来源：http://www.clicksun.net/mis/bbs/showapp.asp?id=16438

        #region 32位程序读写64注册表 

        static UIntPtr HKEY_CLASSES_ROOT = (UIntPtr)0x80000000;
        static UIntPtr HKEY_CURRENT_USER = (UIntPtr)0x80000001;
        static UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002;
        static UIntPtr HKEY_USERS = (UIntPtr)0x80000003;
        static UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005;

        // 关闭64位（文件系统）的操作转向 
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
        // 开启64位（文件系统）的操作转向 
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

        // 获取操作Key值句柄 
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern uint RegOpenKeyEx(UIntPtr hKey, string lpSubKey, uint ulOptions, int samDesired, out IntPtr phkResult);
        //关闭注册表转向（禁用特定项的注册表反射） 
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern long RegDisableReflectionKey(IntPtr hKey);
        //使能注册表转向（开启特定项的注册表反射） 
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern long RegEnableReflectionKey(IntPtr hKey);
        //获取Key值（即：Key值句柄所标志的Key对象的值） 
        [DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved,
        out uint lpType, System.Text.StringBuilder lpData,
        ref uint lpcbData);

        private static UIntPtr TransferKeyName(string keyName)
        {
            switch (keyName)
            {
                case "HKEY_CLASSES_ROOT":
                    return HKEY_CLASSES_ROOT;
                case "HKEY_CURRENT_USER":
                    return HKEY_CURRENT_USER;
                case "HKEY_LOCAL_MACHINE":
                    return HKEY_LOCAL_MACHINE;
                case "HKEY_USERS":
                    return HKEY_USERS;
                case "HKEY_CURRENT_CONFIG":
                    return HKEY_CURRENT_CONFIG;
            }

            return HKEY_CLASSES_ROOT;
        }

        public static string Get64BitRegistryKey(string parentKeyName, string subKeyName, string keyName)
        {
            int KEY_QUERY_VALUE = (0x0001);
            int KEY_WOW64_64KEY = (0x0100);
            int KEY_ALL_WOW64 = (KEY_QUERY_VALUE | KEY_WOW64_64KEY);

            try
            {
                //将Windows注册表主键名转化成为不带正负号的整形句柄（与平台是32或者64位有关） 
                UIntPtr hKey = TransferKeyName(parentKeyName);

                //声明将要获取Key值的句柄 
                IntPtr pHKey = IntPtr.Zero;

                //记录读取到的Key值 
                StringBuilder result = new StringBuilder("".PadLeft(1024));
                uint resultSize = 1024;
                uint lpType = 0;

                //关闭文件系统转向 
                IntPtr oldWOW64State = new IntPtr();
                if (Wow64DisableWow64FsRedirection(ref oldWOW64State))
                {
                    //获得操作Key值的句柄 
                    RegOpenKeyEx(hKey, subKeyName, 0, KEY_ALL_WOW64, out pHKey);

                    //关闭注册表转向（禁止特定项的注册表反射） 
                    RegDisableReflectionKey(pHKey);

                    //获取访问的Key值 
                    RegQueryValueEx(pHKey, keyName, 0, out lpType, result, ref resultSize);

                    //打开注册表转向（开启特定项的注册表反射） 
                    RegEnableReflectionKey(pHKey);
                }

                //打开文件系统转向 
                Wow64RevertWow64FsRedirection(oldWOW64State);

                //返回Key值 
                return result.ToString().Trim();
            }
            catch (Exception ex)
            {
                LMessageBox.ShowWarning(ex.Message);
                return "";
            }
        }

        #endregion
    }
}
